#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

//int main()
//{
//	int a[4] = { 1,2,3,4 };
//	//a是数组名，&a就是取到整个数组的地址，+1，跳过整个数组，再
//	//转换为int*类型，赋值给ptr1
//	int* ptr1 = (int*)(&a + 1);
//	//a是数组名，a没有单独的放置在sizeof的内部，也没有取地址
//	//所以a表示数组首元素的地址，将地址强制转为整型
//	//+1,假设地址为0x10000，再经过强制转换+1后，值为0x10001
//	//之后强制转换为int*,此时，ptr2的类型为int*
//	int* ptr2 = (int*)((int)a + 1);
//	//%x,输出格式为16进制，ptr1[-1]为4，4的16进制也为4
//	//采用小端机器存储(低字节存放在低地址位置，高字节存放在高地址位置)，假设左边为低地址，右边为高地址，转换为16进制，数组a在内存中的
//	//存储如下：
//	//01 00 00 00   02 00 00 00    03 00 00 00   04 00 00 00
//	//ptr2此时应该指向01后面的00，按照内存的读取方式，对ptr2解引用为 02 00 00 00
//	printf("%x,%x", ptr1[-1], *ptr2);
//	return 0;
//}




//


//int main()
//{
//	int a[5][5];
//	// 0 0 0 0 0
//	// 0 0 0 0 0
//	// 0 0 0 0 0
//	// 0 0 0 0 0
//	// 0 0 0 0 0
//	//定义了一个数组指针p，指向的数组有4个元素，每一个元素都是int
//	int(*p)[4];
//	//a是一个二维数组，a没有氮素的放在sizeof的内部，也没有取地址，
//	//说明a表示首元素的地址，也就是第一行的地址，它的类型为int (*)[5]
//	//p的类型为int (*) [4],p每次加1，就会跳过四个整型，即p[1]和p[0]相差4个int
//	p = a;
//	//%p直接打印的是补码
//	//p的类型为int (*) [4],p每次加1，就会跳过四个整型，即p[1]和p[0]相差4个int
//	//所以，p[4]相当于指向了数组第四行的第2个元素，p[4][2]则为数组第四行的第4个元素
//	//p[4][2]相当于a[3][3] ,低地址-高地址为负，-4
//	//-4 转化为16进制表示
//	//10000000 00000000 00000000 00000100
//	//11111111 11111111 11111111 11111011
//	//11111111 11111111 11111111 11111100  12
//	//% p直接打印的是补码
//	printf("%p,%d\n",&p[4][2]-&a[4][2], &p[4][2] - &a[4][2]);
//	return 0;
//}


//int main()
//{
//	int aa[2][5] = {1,2,3,4,5,6,7,8,9,10};
//	//aa是一个数组名，&aa拿到的是整个数组，+1，数组后的地址
//	//强制转换为int*,赋值给ptr1
//	//aa是一个数组名，没有单独的放在sizeof的内部，也没有取地址
//	//所以，aa表示首元素的地址，也就是第一行的地址，是一个一维数组
//	//+1，跳过第一行，
//	int* ptr1 = (int*)(&aa + 1);
//	//对于二维数组来说，*aa，就是a[0]
//	//他有两个方括号需要解引用2次
//	//*(aa+1) 就是aa[1],再用int* 强制转换，没有太大的意义
//	int* ptr2 = (*(aa+1));//aa[1]
//	
//	printf("%d,%d",*(ptr1-1),*(ptr2-1));
//	return 0;
//}



//int main()
//{
//	//a是一个数组，数组的每一个元素都是char*
//	//数组中存放的是各字符串首元素的地址
//	char* a[] = {"work","at","alibaba"};
//	//a是数组名，表示数组首元素的地址
//	//pa是一个指针，该指针指向的元素为char*，再将a赋值给pa后，它指向w
//	char* *pa = a;
//	//如何理解pa++
//	//假设有一个整型数组 int a[5]={1,2,3,4,5};
//	// int *p=a;
//	//p++;
//	//与上述过程一致
//	//pa++后指向a
//	pa++;
//	printf("%s\n",*pa);
//	return 0;
//}


int main()
{
	//c中存放各字符串的首地址
	char* c[] = {"ENTER","NEW","POINT","FIRST"};
	//c+3 F的地址，c+2 P 的地址，c+1 N 的地址 c E 的地址
	char** cp[] = {c+3,c+2,c+1,c};
	//cpp指向c+3，cpp+1指向 c+2，cpp+2指向 c+1 ，cpp+3 指向 c
	char*** cpp = cp;
	printf("%s\n", **++cpp);//POINT
	printf("%s\n", *-- * ++cpp + 3);//NT
	printf("%s\n", *cpp[-2] + 3);//ENTER
	printf("%s\n",cpp[-1][-1]+1);
	return 0;
}